import { Injectable } from '@angular/core' // 从Angular核心库中引入Injectable装饰器
import { debounceTime, scan } from 'rxjs' // 从rxjs库中引入bufferTime操作符
import { TerminalDecorator, BaseTerminalTabComponent, BaseSession } from 'tabby-terminal' // 从tabby-terminal库中引入相关类

import { ClippyService } from './clippy.service' // 引入自定义的ClippyService服务

async function SendToAIService (matchedContent: string) {
    const url = 'http://localhost:8080/terminal'
    const payload = {
        content: matchedContent,
    }
    console.log('send to third party:', payload)
    try {
        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(payload),
        })

        const data = await response.json()
        console.log('from third party data:', data)
        if (data.success) {
            return data.answer
        } else {
            console.error(`Error: ${data.errMsg}`)
            throw new Error(data.errMsg)
        }
    } catch (error) {
        console.error('Request failed', error)
        throw error
    }
}

@Injectable()
export class ClippyDecorator extends TerminalDecorator {
    constructor (
        private clippy: ClippyService,
    ) {
        super()
    }

    attach (tab: BaseTerminalTabComponent<any>): void {
        tab.input$.pipe(
            scan((acc, curr) => {
                // 这里的curr是utf8编码的buffer，所以\b 是8，\r是13，\n是10
                const str = curr.toString()

                // 如果大于1个字节，那么就直接push到acc中
                if (curr.length > 1) {
                    acc.push(str)
                    return acc
                }

                for (const char of curr) {
                    // char 是 ASCII 码值
                    switch (char) {
                        case 127: // 删除一个字符
                            if (acc.length > 0) { acc.pop() }
                            break
                        case 13: // 回车
                        case 10: // 换行
                            acc.length = 0 // 清空数组
                            break
                        default:
                            acc.push(str)
                            break
                    }
                }

                return acc
            }, [] as string[]),
            debounceTime(3000), // Add a debounce time to batch process input
        ).subscribe(buffer => {
            // 从buffer中提取用户输入的内容
            const accumulatedInput = buffer.join('')
            // ## Docker 如何安装？ ##
            const specialPattern = /##([^#]+)##/
            const match = specialPattern.exec(accumulatedInput)

            if (match) {
                const matchedContent = match[1]
                console.log('detect special pattern:', matchedContent)
                this.clippy.speak('Let me think about it')
                // this.clippy.ThinkAnimate()
                SendToAIService(matchedContent).then((res) => {
                    tab.sendInput('\r')
                    if (res.show) {
                        this.clippy.speak(res.answer)
                    } else {
                        tab.sendInput(res.answer)
                    }
                })

                // Clear the accumulated content after handling
                buffer.length = 0
            }
        })

        // 监控会话改变事件
        tab.sessionChanged$.subscribe(session => {
            if (session) {
                this.attachToSession(session)
            }
        })

        if (tab.session) {
            this.attachToSession(tab.session)
        }
    }

    private attachToSession (session: BaseSession) {
        session.output$.subscribe(data => {
            if (data.includes('command not found')) {
                this.clippy.speak('It looks like you\'ve typed in an incorrect command. Consider typing in a correct command instead.')
            }
        })
    }
}
